/*
 * SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
 *
 * SPDX-License-Identifier: MulanPSL-2.0
 */
#![allow(
    dead_code,
    non_upper_case_globals,
    unused_assignments,
    unused_mut,
    clippy::never_loop
)]
use crate::common::*;
extern "C" {
    fn malloc(_: libc::c_ulong) -> *mut libc::c_void;
    fn realloc(_: *mut libc::c_void, _: libc::c_ulong) -> *mut libc::c_void;
    fn free(_: *mut libc::c_void);
    fn strlen(_: *const libc::c_char) -> libc::c_ulong;
    fn sudo_warnx_nodebug_v1(fmt: *const libc::c_char, _: ...);
    fn sudo_warn_gettext_v1(
        domainname: *const libc::c_char,
        msgid: *const libc::c_char,
    ) -> *mut libc::c_char;
    fn sudo_strlcpy(dst: *mut libc::c_char, src: *const libc::c_char, siz: size_t) -> size_t;
    fn hexchar(s: *const libc::c_char) -> libc::c_int;
    fn sudo_debug_exit_bool_v1(
        func: *const libc::c_char,
        file: *const libc::c_char,
        line: libc::c_int,
        subsys: libc::c_int,
        ret: bool,
    );
    fn sudo_debug_printf2_v1(
        func: *const libc::c_char,
        file: *const libc::c_char,
        line: libc::c_int,
        level: libc::c_int,
        fmt: *const libc::c_char,
        _: ...
    );
    static mut sudoers_subsystem_ids: [libc::c_uint; 0];
    fn sudoerserror(_: *const libc::c_char);
    static mut sudoerslval: YYSTYPE;
}

#[derive(Copy, Clone, BitfieldStruct)]
#[repr(C)]
pub struct cmndtag {
    #[bitfield(name = "nopasswd", ty = "libc::c_int", bits = "0..=2")]
    #[bitfield(name = "noexec", ty = "libc::c_int", bits = "3..=5")]
    #[bitfield(name = "setenv", ty = "libc::c_int", bits = "6..=8")]
    #[bitfield(name = "log_input", ty = "libc::c_int", bits = "9..=11")]
    #[bitfield(name = "log_output", ty = "libc::c_int", bits = "12..=14")]
    #[bitfield(name = "send_mail", ty = "libc::c_int", bits = "15..=17")]
    #[bitfield(name = "follow", ty = "libc::c_int", bits = "18..=20")]
    pub nopasswd_noexec_setenv_log_input_log_output_send_mail_follow: [u8; 3],
    #[bitfield(padding)]
    pub c2rust_padding: [u8; 1],
}
#[derive(Copy, Clone)]
#[repr(C)]
pub struct runascontainer {
    pub runasusers: *mut member,
    pub runasgroups: *mut member,
}
#[derive(Copy, Clone)]
#[repr(C)]
pub union YYSTYPE {
    pub cmndspec: *mut cmndspec,
    pub defaults: *mut defaults,
    pub member: *mut member,
    pub runas: *mut runascontainer,
    pub privilege: *mut privilege,
    pub digest: *mut command_digest,
    pub command: sudo_command,
    pub options: command_options,
    pub tag: cmndtag,
    pub string: *mut libc::c_char,
    pub tok: libc::c_int,
}
static mut arg_len: libc::c_uint = 0 as libc::c_int as libc::c_uint;
static mut arg_size: libc::c_uint = 0 as libc::c_int as libc::c_uint;
#[no_mangle]
pub fn fill_txt(mut src: *const libc::c_char, mut len: size_t, mut olen: size_t) -> bool {
    let mut dst: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
    let mut h: libc::c_int = 0;
    unsafe {
        debug_decl!(SUDOERS_DEBUG_PARSER!());
    }

    unsafe {
        dst = (if olen != 0 {
            realloc(
                sudoerslval.string as *mut libc::c_void,
                olen.wrapping_add(len)
                    .wrapping_add(1 as libc::c_int as libc::c_ulong),
            )
        } else {
            malloc(len.wrapping_add(1 as libc::c_int as libc::c_ulong))
        }) as *mut libc::c_char;
        if dst.is_null() {
            sudo_warnx!(
                b"%s: %s\0" as *const u8 as *const libc::c_char,
                get_function_name!(),
                b"unable to allocate memory\0" as *const u8 as *const libc::c_char
            );
            sudoerserror(std::ptr::null::<libc::c_char>());
            debug_return_bool!(false);
        }
        sudoerslval.string = dst;

        /* Copy the string and collapse any escaped characters. */
        dst = dst.offset(olen as isize);
        loop {
            let fresh0 = len;
            len = len.wrapping_sub(1);
            if fresh0 == 0 {
                break;
            }
            if *src as libc::c_int == '\\' as i32 && len != 0 {
                if *src.offset(1 as libc::c_int as isize) as libc::c_int == 'x' as i32
                    && len >= 3 as libc::c_int as libc::c_ulong
                    && {
                        h = hexchar(src.offset(2 as libc::c_int as isize));
                        h != -(1 as libc::c_int)
                    }
                {
                    let fresh1 = dst;
                    dst = dst.offset(1);
                    *fresh1 = h as libc::c_char;
                    src = src.offset(4 as libc::c_int as isize);
                    len = (len as libc::c_ulong).wrapping_sub(3 as libc::c_int as libc::c_ulong)
                        as size_t as size_t;
                } else {
                    src = src.offset(1);
                    len = len.wrapping_sub(1);
                    let fresh2 = src;
                    src = src.offset(1);
                    let fresh3 = dst;
                    dst = dst.offset(1);
                    *fresh3 = *fresh2;
                }
            } else {
                let fresh4 = src;
                src = src.offset(1);
                let fresh5 = dst;
                dst = dst.offset(1);
                *fresh5 = *fresh4;
            }
        }
        *dst = '\0' as i32 as libc::c_char;
        debug_return_bool!(true);
    }
}
#[no_mangle]
pub fn append(mut src: *const libc::c_char, mut len: size_t) -> bool {
    let mut olen: libc::c_int = 0 as libc::c_int;
    unsafe {
        debug_decl!(SUDOERS_DEBUG_PARSER!());
    }

    unsafe {
        if !(sudoerslval.string).is_null() {
            olen = strlen(sudoerslval.string) as libc::c_int;
        }
    }

    unsafe {
        debug_return_bool!(fill_txt(src, len, olen as size_t));
    }
}
#[no_mangle]
pub fn fill_cmnd(mut src: *const libc::c_char, mut len: size_t) -> bool {
    let mut dst: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();
    let mut i: size_t = 0;
    unsafe {
        debug_decl!(SUDOERS_DEBUG_PARSER!());
    }

    unsafe {
        arg_size = 0 as libc::c_int as libc::c_uint;
        arg_len = arg_size;
        sudoerslval.command.cmnd =
            malloc(len.wrapping_add(1 as libc::c_int as libc::c_ulong)) as *mut libc::c_char;
        dst = sudoerslval.command.cmnd;
        if dst.is_null() {
            sudo_warnx!(
                b"%s: %s\0" as *const u8 as *const libc::c_char,
                get_function_name!(),
                b"unable to allocate memory\0" as *const u8 as *const libc::c_char
            );

            sudoerserror(std::ptr::null_mut::<libc::c_char>());
            debug_return_bool!(false);
        }
        sudoerslval.command.args = std::ptr::null_mut::<libc::c_char>();

        /* Copy the string and collapse any escaped sudo-specific characters. */
        i = 0 as libc::c_int as size_t;
        while i < len {
            if *src.offset(i as isize) as libc::c_int == '\\' as i32
                && i != len.wrapping_sub(1 as libc::c_int as libc::c_ulong)
                && (*src.offset(i.wrapping_add(1 as libc::c_int as libc::c_ulong) as isize)
                    as libc::c_int
                    == ',' as i32
                    || *src.offset(i.wrapping_add(1 as libc::c_int as libc::c_ulong) as isize)
                        as libc::c_int
                        == ':' as i32
                    || *src.offset(i.wrapping_add(1 as libc::c_int as libc::c_ulong) as isize)
                        as libc::c_int
                        == '=' as i32
                    || *src.offset(i.wrapping_add(1 as libc::c_int as libc::c_ulong) as isize)
                        as libc::c_int
                        == ' ' as i32
                    || *src.offset(i.wrapping_add(1 as libc::c_int as libc::c_ulong) as isize)
                        as libc::c_int
                        == '\t' as i32
                    || *src.offset(i.wrapping_add(1 as libc::c_int as libc::c_ulong) as isize)
                        as libc::c_int
                        == '#' as i32)
            {
                i = i.wrapping_add(1);
                let fresh6 = dst;
                dst = dst.offset(1);
                *fresh6 = *src.offset(i as isize);
            } else {
                let fresh7 = dst;
                dst = dst.offset(1);
                *fresh7 = *src.offset(i as isize);
            }
            i = i.wrapping_add(1);
        }
        *dst = '\0' as i32 as libc::c_char;
    }
    unsafe {
        debug_return_bool!(true);
    }
}
#[no_mangle]
pub fn fill_args(mut s: *const libc::c_char, mut len: size_t, mut addspace: libc::c_int) -> bool {
    let mut new_len: libc::c_uint = 0;
    let mut p: *mut libc::c_char = std::ptr::null_mut::<libc::c_char>();

    unsafe {
        debug_decl!(SUDOERS_DEBUG_PARSER!());
    }

    unsafe {
        if arg_size == 0 as libc::c_int as libc::c_uint {
            addspace = 0 as libc::c_int;
            new_len = len as libc::c_uint;
        } else {
            new_len = (arg_len as libc::c_ulong)
                .wrapping_add(len)
                .wrapping_add(addspace as libc::c_ulong) as libc::c_uint;
        }
        'bad: loop {
            if new_len >= arg_size {
                /* Allocate in increments of 128 bytes to avoid excessive realloc(). */
                arg_size = new_len
                    .wrapping_add(1 as libc::c_int as libc::c_uint)
                    .wrapping_add(127 as libc::c_int as libc::c_uint)
                    & !(127 as libc::c_int) as libc::c_uint;

                p = realloc(
                    sudoerslval.command.args as *mut libc::c_void,
                    arg_size as libc::c_ulong,
                ) as *mut libc::c_char;

                if p.is_null() {
                    sudo_warnx!(
                        b"%s: %s\0" as *const u8 as *const libc::c_char,
                        get_function_name!(),
                        b"unable to allocate memory\0" as *const u8 as *const libc::c_char
                    );
                    break 'bad;
                } else {
                    sudoerslval.command.args = p;
                }
            }

            /* Efficiently append the arg (with a leading space if needed). */
            p = (sudoerslval.command.args).offset(arg_len as isize);
            if addspace != 0 {
                let fresh8 = p;
                p = p.offset(1);
                *fresh8 = ' ' as i32 as libc::c_char;
            }
            len = (arg_size as libc::c_long
                - p.offset_from(sudoerslval.command.args) as libc::c_long)
                as size_t;

            if sudo_strlcpy(p, s, len) >= len {
                sudo_warnx!(
                    b"internal error, %s overflow\0" as *const u8 as *const libc::c_char,
                    get_function_name!()
                );
                break 'bad;
            }
            arg_len = new_len;
            debug_return_bool!(true);
        } //  'bad loop

        sudoerserror(std::ptr::null::<libc::c_char>());
        free(sudoerslval.command.args as *mut libc::c_void);
        sudoerslval.command.args = std::ptr::null_mut::<libc::c_char>();
        arg_size = 0 as libc::c_int as libc::c_uint;
        arg_len = arg_size;
    }
    unsafe {
        debug_return_bool!(false);
    }
}

/*
 * Check to make sure an IPv6 address does not contain multiple instances
 * of the string "::".  Assumes strlen(s) >= 1.
 * Returns true if address is valid else false.
 */
#[no_mangle]
pub fn ipv6_valid(mut s: *const libc::c_char) -> bool {
    let mut nmatch: libc::c_int = 0 as libc::c_int;
    unsafe {
        debug_decl!(SUDOERS_DEBUG_PARSER!());
    }

    unsafe {
        while *s as libc::c_int != '\0' as i32 {
            if *s.offset(0 as libc::c_int as isize) as libc::c_int == ':' as i32
                && *s.offset(1 as libc::c_int as isize) as libc::c_int == ':' as i32
            {
                nmatch += 1;
                if nmatch > 1 as libc::c_int {
                    break;
                }
            }
            if *s.offset(0 as libc::c_int as isize) as libc::c_int == '/' as i32 {
                nmatch = 0 as libc::c_int; /* reset if we hit netmask */
            }
            s = s.offset(1);
        }
    }
    unsafe {
        debug_return_bool!(nmatch <= 1);
    }
}
